package com.qf.java2201.edu.userservice.config;

import com.qf.java2201.edu.userservice.filter.TokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

/**
 * @date 2022/6/5
 * @desc
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {



    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;
    @Autowired
    private LogoutSuccessHandler logoutSuccessHandler;
    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    private AccessDeniedHandler accessDeniedHandler;



    private static final String[] WHITELIST_URL = {"/userservice/user/login", "/captchaImage","/v2/**","/doc.html","/swagger/**","/webjars/**","/swagger-resources/**"};
    private static final String[] WHITELIST_SOURCE = {"/**/*.css", "/webjars/**"};


    // 注入 PasswordEncoder 类到 spring 容器中
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private UserDetailsService userDetailsService;




    @Autowired
    private TokenFilter tokenFilter;


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }

    //这种方式 释放静态资源也可以
    //@Override
    //public void configure(WebSecurity web) throws Exception {
    //    web.ignoring().antMatchers("/swagger/**")
    //            .antMatchers("/swagger-ui.html")
    //            .antMatchers("/webjars/**")
    //            .antMatchers("/v2/**")
    //            .antMatchers("/swagger-resources/**")
    //            .antMatchers("/doc.html");
    //
    //}




    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //退出登录状态
        //http.logout().logoutUrl("/logout").logoutSuccessUrl("/").permitAll();
        http.logout().logoutUrl("/userservice/user/logout").logoutSuccessHandler(logoutSuccessHandler);


        http   //.formLogin()  //     自定义登录页面
                //.loginPage("/login.html")  // 指定登录页面路径  如果直接是页面  必须在static中
                //.loginPage("/")  // 指定登录页面路径  通过controller 跳转  则在templates 中
                //.loginProcessingUrl("/userservice/user/login")    //登录表单访问路径
                //.successHandler(authenticationSuccessHandler)
                //.defaultSuccessUrl("/main").permitAll() // 登陆成功之后跳转路径
                //.successHandler(authenticationSuccessHandler)
                //.failureHandler(authenticationFailureHandler)
                //.and()
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler)
                .and()
                .authorizeRequests()
                .antMatchers(WHITELIST_URL).anonymous()
                //.antMatchers(WHITELIST_URL).permitAll()
                //.antMatchers("/","layui/**","/user/anno") //配置无需认证的请求路径
                .antMatchers(HttpMethod.GET, WHITELIST_SOURCE) //配置无需认证的请求路径
                .permitAll() // 指定 URL 无需保护。
                .anyRequest() // 其他请求
                .authenticated() //需要认证

                .and().csrf().disable(); //关闭csrf防护  这个一定要加上

        // 解决不允许显示在iframe的问题  禁用网页嵌入iframe
        http.headers().frameOptions().disable();
        http.headers().cacheControl();

        //配置自定义过滤器
        http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);

        //访问拒绝页面
        //http.exceptionHandling().accessDeniedPage("/unauth");

        // 开启记住我功能
        // http.rememberMe()
        //        .tokenValiditySeconds(60)   // 单位是秒
        //.tokenRepository(tokenRepository)
        //        .userDetailsService(userDetailsService);
    }


    /**
     * 解决无法直接注入AuthenticationManager
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}
